package defaulter

import (
	"fmt"
	"net/http"
	"net/url"

	"gitee.com/haodreams/golib/autoroute/controller"
	"gitee.com/haodreams/golib/minauth"
	"github.com/gin-gonic/gin"
)

// LoginController 授权相关的操作
type LoginController struct {
	controller.Controller
}

/**
 * @description: 开启默认的认证
 * @param {*} cb 扩展的认证方式
 * @return {*}
 */
func UseDefaultAuth(defaultUser func() (user, passwd string), cb ...func(*gin.Context) (any, error)) {
	if len(cb) > 0 && cb != nil {
		controller.SetNeedAuthCallback(cb[0])
	} else {
		controller.SetNeedAuthCallback(minauth.CallbackNeedAuth)
	}
	initUser(defaultUser)
}

func initUser(defaultUser func() (user, passwd string)) {
	minauth.Init(defaultUser)
}

// Index ... 登录对话框
// 登录方式1
func (m *LoginController) Index() {
	param := m.GetParam()
	if m.IsPost() {
		username := param.GetTrimString("username")
		password := param.GetTrimString("password")

		if username == "" {
			m.Error("无效的用户名")
			return
		}

		if password == "" {
			m.Error("无效的密码")
			return
		}

		user := minauth.GetUsers().GetUser(username)
		if user == nil {
			m.ErrorWithCode("无效的用户名或密码", http.StatusUnauthorized)
			return
		}

		if user.GetName() == username && user.GetPassword() == password {
			clientIP := m.ClientIP()
			sess := minauth.Register(username, "", "", clientIP)
			m.AddCookie("uid", sess.SID, 3600*24*360)
			m.Map["data"] = sess.SID
			m.Msg("登录成功")
			return
		}
		m.Error("无效的用户名或密码")
		return
	}
	m.Map["lastURL"] = param.GetTrimString("lastURL")
	m.Map["lastMsg"] = param.GetTrimString("lastMsg")
	m.Display()
}

// Logout ...
func (m *LoginController) Logout() {
	uid, err := m.Cookie("uid")
	if err != nil {
		m.Msg("成功退出")
		//m.Redirect(302, "/go/login/login")
		return
	}

	minauth.RemoveBySID(uid)
	m.AddCookie("uid", "", -1)
	m.Msg("成功退出")
	//m.Redirect(301, "/go/login/login")
}

// Modify 修改密码
func (m *LoginController) Modify() {
	if m.IsPost() {
		pwd := ""
		newpwd := ""
		contentType := m.ContentType()
		if contentType == "application/json" {
			type User struct {
				Pwd    string `json:"pwd"`
				NewPwd string `json:"newpwd"`
			}
			var u User
			err := m.ShouldBindJSON(&u)
			if err != nil {
				m.Msg(err.Error())
				return
			}
			pwd = u.Pwd
			newpwd = u.NewPwd
			pwd = minauth.Hash(pwd)
			newpwd = minauth.Hash(newpwd)
		} else {
			param := m.GetParam()
			pwd = param.GetTrimString("pwd")
			newpwd = param.GetTrimString("newpwd")
		}

		username := ""
		var err error

		uid := m.Request.Header.Get("Authorization")
		if uid == "" {
			//step1 : 检查cookie中是否带有参数
			uid, err = m.Cookie("uid")
			if err != nil || uid == "" {
				//step2 : 检查参数中是否带有uid
				vals, _ := url.ParseQuery(m.Request.URL.RawQuery)
				uids := vals["uid"]
				if len(uids) > 0 {
					uid = uids[0]
				} else {
					m.ErrorWithCode("登录已经过期,请重新登录", http.StatusUnauthorized)
					return
				}
			}
		}

		sess, err := minauth.FindBySID(uid)
		if err != nil || sess == nil {
			m.ErrorWithCode("登录已经过期,请重新登录", http.StatusUnauthorized)
			return
		}
		username = sess.Name

		user := minauth.GetUsers().GetUser(username)
		if user == nil {
			m.ErrorWithCode("登录已经过期,请重新登录", http.StatusUnauthorized)
			return
		}

		if user.GetPassword() != pwd {
			m.Error("当前密码错误")
			return
		}

		user.SetPassword(newpwd)
		err = minauth.Save()
		if err != nil {
			user.SetPassword(pwd)
			m.Msg("密码更新失败")
			return
		}

		m.Msg("密码修改成功")
		return
	}
	m.Display()
}

// Delete 删除用户
func (m *LoginController) Delete() {
}

// Status 登录状态
func (m *LoginController) Status() {
	uid, err := m.Cookie("uid")
	if err != nil {
		m.Error("需要重新登录")
		return
	}

	_, err = minauth.FindBySID(uid)
	if err != nil {
		m.Error("登录已经过期，需要重新登录")
		return
	}
	m.Msg("OK")
}

// @tags 用户管理
// @Summary 用户登录
// @Description 根据用户名和密码生成uid
// @Param username formData string true "用户名"
// @Param password formData string true "密码"
// @Produce plain
// @Success 200 {string} string "ok" "认证成功"
// @Failure 401 {string} string "code：401 需要认证"
// @Failure 412 {string} string "code：412 参数错误"
// @Router /login/login [post]
func (m *LoginController) Login() {
	param := m.GetParam()
	username := param.GetTrimString("username")
	password := param.GetTrimString("password")

	if username == "" {
		m.ErrorWithCode("无效的用户名", http.StatusUnauthorized)
		return
	}

	if password == "" {
		m.ErrorWithCode("无效的密码", http.StatusUnauthorized)
		return
	}

	user := minauth.GetUsers().GetUser(username)
	if user == nil {
		m.ErrorWithCode("无效的用户名或密码", http.StatusUnauthorized)
		return
	}

	if user.GetName() == username && user.GetPassword() == password {
		clientIP := m.ClientIP()
		sess := minauth.Register(username, "", "", clientIP)
		m.AddCookie("uid", sess.SID, 3600*24*7)
		m.Map["data"] = sess.SID
		m.Msg("登录成功")
		return
	}
	m.ErrorWithCode("用户名或密码不正确", http.StatusUnauthorized)
}

// 自动登录使用
func (m *LoginController) AutoLogin() {
	param := m.GetParam()
	username := param.GetTrimString("username")
	password := param.GetTrimString("password")
	if username == "" {
		m.ErrorWithCode("无效的用户名", http.StatusUnauthorized)
		return
	}
	if password == "" {
		m.ErrorWithCode("无效的密码", http.StatusUnauthorized)
		return
	}
	data := fmt.Sprintf("username=%s&password=%s", username, password)
	html := `<!DOCTYPE html><html>	
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width,initial-scale=1">
		<title>auto login</title>
		<script>
			fetch("/v1/login/login", {
				method: "POST",
				headers: {
					"Content-Type": "application/x-www-form-urlencoded"
				},
				body: "` + data + `"
			})
				.then((response) => response.json())
				.then((data) => {
					console.log(data);
					if (data.code == 200 || data.code == 0) {
						localStorage.setItem("token", data.data);
						window.location.href = "/";
					} else {
						document.write(JSON.stringify(data))
					}
				})
				.catch(function (err) {
					if (err.response) {
						let response = err.response;
						console.log(response);
						document.write(String(response))
					} else {
						console.log(String(err));
					}
				});
		</script>
	</head>	
	<body></body>	
	</html>`
	m.Writer.Header().Add("Content-Type", "text/html")
	m.Writer.WriteHeader(200)
	m.Writer.Write([]byte(html))
}

func (m *LoginController) HashData() {
	param := m.GetParam()
	data := param.GetTrimString("data")
	if data == "" {
		m.Error("无有效数据")
		return
	}
	m.Msg(minauth.Hash(data))
}
